package com.sam.im.heiqun.utils;

import java.security.DigestException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

import javax.crypto.Cipher;

import com.google.gson.Gson;

import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.SHA1Digest;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.MD2Digest;
import org.bouncycastle.crypto.digests.MD4Digest;
import org.bouncycastle.crypto.digests.MD5Digest;
import org.bouncycastle.jce.provider.BouncyCastleProvider;


/**
 *@auth qiuxueyun
*/
/**
 * RSA 工具类。提供加密，解密，生成密钥对等方法。
 * 需要到http://www.bouncycastle.org下载bcprov-jdk14-123.jar。
 *
 */
public class RSAUtils {
    public static final String KEY_ALGORTHM="RSA";//
    public static final String SIGNATURE_ALGORITHM="MD5withRSA";

    public static final String PUBLIC_KEY = "RSAPublicKey";//公钥
    public static final String PRIVATE_KEY = "RSAPrivateKey";//私钥

        /**
         * BASE64解密
         * @param key
         * @return
         * @throws Exception
         */
    public static byte[] decryptBASE64(String key) throws Exception{
        return Base64Utils.decode(key);
    }



      /**
         * BASE64加密
         * @param key
         * @return
         * @throws Exception
         */
    public static String encryptBASE64(byte[] key)throws Exception{
        return Base64Utils.encode(key);
    }


        /**
         * 初始化密钥
         * @return
         * @throws Exception
         */
        public static Map<String,Object> initKey()throws Exception{
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY_ALGORTHM);
            keyPairGenerator.initialize(1024);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();

            //公钥
            RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
            //私钥
            RSAPrivateKey privateKey =  (RSAPrivateKey) keyPair.getPrivate();

            Map<String,Object> keyMap = new HashMap<String, Object>(2);
            keyMap.put(PUBLIC_KEY, publicKey);
            keyMap.put(PRIVATE_KEY, privateKey);

            return keyMap;
        }

        /**
         * 取得公钥，并转化为String类型
         * @param keyMap
         * @return
         * @throws Exception
         */
        public static String getPublicKey(Map<String, Object> keyMap)throws Exception{
            Key key = (Key) keyMap.get(PUBLIC_KEY);
            return encryptBASE64(key.getEncoded());
        }

        /**
         * 取得私钥，并转化为String类型
         * @param keyMap
         * @return
         * @throws Exception
         */
        public static String getPrivateKey(Map<String, Object> keyMap) throws Exception{
            Key key = (Key) keyMap.get(PRIVATE_KEY);
            return encryptBASE64(key.getEncoded());
        }


        /**
         * 用公钥加密
         * @param data  加密数据
         * @param key   密钥
         * @return
         * @throws Exception
         */
        public static byte[] encryptByPublicKey(byte[] data,String key)throws Exception{
            //对公钥解密
            byte[] keyBytes = decryptBASE64(key);
            //取公钥
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
            Key publicKey = keyFactory.generatePublic(x509EncodedKeySpec);

            //对数据解密
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);

            return cipher.doFinal(data);
        }


        /**
         * 用私钥解密
         * @param data  加密数据
         * @param key   密钥
         * @return
         * @throws Exception
         */
        public static byte[] decryptByPrivateKey(byte[] data,String key)throws Exception{
            //对私钥解密
            byte[] keyBytes = decryptBASE64(key);
            //System.out.println("+++++++++++++++++"+keyBytes);
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
            Key privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            //对数据解密
            Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
            cipher.init(Cipher.DECRYPT_MODE, privateKey);

            return cipher.doFinal(data);
        }



        /**
         *  用私钥对信息生成数字签名
         * @param data  //加密数据
         * @param privateKey    //私钥
         * @return
         * @throws Exception
         */
        public static String sign(byte[] data,String privateKey)throws Exception{
            //解密私钥
            byte[] keyBytes = decryptBASE64(privateKey);
            //构造PKCS8EncodedKeySpec对象
            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(keyBytes);
            //指定加密算法
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
            //取私钥匙对象
            PrivateKey privateKey2 = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
            //用私钥对信息生成数字签名
            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initSign(privateKey2);
            signature.update(data);

            return encryptBASE64(signature.sign());
        }



        /**
         * 校验数字签名
         * @param data  加密数据
         * @param publicKey 公钥
         * @param sign  数字签名
         * @return
         * @throws Exception
         */
        public static boolean verify(byte[] data,String publicKey,String sign)throws Exception{
            //解密公钥
            byte[] keyBytes = decryptBASE64(publicKey);
            //构造X509EncodedKeySpec对象
            X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(keyBytes);
            //指定加密算法
            KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORTHM);
            //取公钥匙对象
            PublicKey publicKey2 = keyFactory.generatePublic(x509EncodedKeySpec);

            Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
            signature.initVerify(publicKey2);
            signature.update(data);
            //验证签名是否正常
            return signature.verify(decryptBASE64(sign));

        }
        public static void main(String[] args) throws Exception {
        	Map<String, Object> maps = RSAUtils.initKey();
            String rsaPublicKey = getPublicKey(maps);
            String rsaPrivateKey = getPrivateKey(maps);
            System.out.println("公钥为："+rsaPublicKey);
            System.out.println("私钥为："+rsaPrivateKey);
            //String content = "{name:tansen,age:25,sex:man,address:湖南省常德市澧县}";
            Map<String, Object> map = new HashMap<>();
            map.put("name", "凌芳");
            map.put("age", "22");
            String content = map+"";

            try {

            } catch (Exception e) {
                e.printStackTrace();
            }
            byte[] result_m = null;
            //2.使用公钥加密
            try {
                System.out.println("加密前=="+content);
                result_m = RSAUtils.encryptByPublicKey(content.getBytes(), rsaPublicKey);
                content = encryptBASE64(result_m);
                //content = new String(result_m);
                System.out.println("加密后=="+content);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //3.私钥解密
            try {
            	//String str = "Y6f1/ygM8XhAqZmCzjqcwgJVvwp33naZri4PbPc6InUykkdmV20uhfLDkkBePr6MIRwamRx9bTAvrv0QNU+N+FyEYYyx8Zcze4v2WzqGcz06j7NtF1W94al+UCLRkWHQ/JPEQyojoaQIrLMSuyaRrEnD2ut17SIm8kHxmsK4TLc=";
                byte[] b1 = decryptBASE64(content);
                byte[] b2 = decryptByPrivateKey(b1, rsaPrivateKey);
                content = new String(b2);
                System.out.println("解密后=="+content);
                //JSONObject json_test = JSONObject.fromObject(content);
               // System.out.println(json_test);

               Gson gson = new Gson();
               Map<String, Object> m = new HashMap<String, Object>();
               m = gson.fromJson(content, map.getClass());

               System.out.println("map的值为:"+m.get("name"));
            } catch (Exception e) {
                e.printStackTrace();
            }

            //4.私钥加签
            String sign = null;
            try {
                sign = sign(content.getBytes(), rsaPrivateKey);
                System.out.println("签名=="+sign);
            } catch (Exception e) {
                e.printStackTrace();
            }
            //5.公钥验签
            try {
                boolean flag = verify(content.getBytes(), rsaPublicKey, sign);
                System.out.println("延签结果=="+flag);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
}

